﻿namespace Journey.Security
{
    using System;
    using System.Web;
    using System.Web.Security;

    /// <summary>
    /// 认证服务。
    /// </summary>
    public class AuthenticationService : IAuthenticationService
    {
        /// <summary>
        /// 会员服务。
        /// </summary>
        private readonly IMembershipService _membershipService;

        /// <summary>
        /// 初始化认证服务。
        /// </summary>
        /// <param name="membershipService">会员服务。</param>
        public AuthenticationService(IMembershipService membershipService)
        {
            this._membershipService = membershipService;

            //间隔 14 天。
            this.ExpirationTimeSpan = new TimeSpan(14, 0, 0, 0);
        }

        /// <summary>
        /// 过期时间时隔。
        /// </summary>
        public TimeSpan ExpirationTimeSpan { get; set; }

        /// <summary>
        /// 登录。
        /// </summary>
        /// <param name="accountNumber">用户账号。</param>
        /// <param name="name">用户昵称。</param>
        /// <param name="createPersistentCookie">如果票证将存储在持久性 Cookie 中（跨浏览器会话保存），则为 true；否则为 false。 如果该票证存储在 URL 中，将忽略此值。</param>
        public void SignIn(string accountNumber, string name, bool createPersistentCookie)
        {
            if (string.IsNullOrWhiteSpace(accountNumber))
            {
                throw new ArgumentNullException("accountNumber", "账号不可以是空的。");
            }

            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException("name", "昵称不可以是空的。");
            }

            var now = DateTime.Now;

            var userData = accountNumber;

            var ticket = new FormsAuthenticationTicket(
                1 /*version*/,
                name,
                now,
                now.Add(ExpirationTimeSpan),
                createPersistentCookie,
                userData,
                FormsAuthentication.FormsCookiePath);

            var encryptedTicket = FormsAuthentication.Encrypt(ticket);

            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
            {
                HttpOnly = true,
                Secure = FormsAuthentication.RequireSSL,
                Path = FormsAuthentication.FormsCookiePath
            };
            if (FormsAuthentication.CookieDomain != null)
            {
                cookie.Domain = FormsAuthentication.CookieDomain;
            }

            if (createPersistentCookie)
            {
                cookie.Expires = ticket.Expiration;
            }

            var httpContext = HttpContext.Current;

            httpContext.Response.Cookies.Add(cookie);
        }

        /// <summary>
        /// 登出。
        /// </summary>
        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }

        /// <summary>
        /// 获得已认证的用户。
        /// </summary>
        /// <remarks>
        /// 该方法获得的是已登录的用户，如果是未登录的，则返回 AnonymousUser 类的实例。
        /// </remarks>
        /// <returns>用户实体。</returns>
        public IUser GetAuthenticatedUser()
        {
            var httpContext = HttpContext.Current;
            if (httpContext == null || !httpContext.Request.IsAuthenticated || !(httpContext.User.Identity is FormsIdentity))
            {
                return this._membershipService.GetAnonymousUser();
            }

            var user = this._membershipService.GetUser(httpContext.User.GetCurrentAccountNumber()) ??
                         (IUser)this._membershipService.GetAnonymousUser();

            return user;
        }
    }
}